package com.ht.system.service.impl;

import com.ht.common.core.constant.CacheConstants;
import com.ht.common.core.constant.Constants;
import com.ht.common.core.constant.UserConstants;
import com.ht.common.core.domain.LoginUser;
import com.ht.common.core.domain.LoginUserEntInfo;
import com.ht.common.core.domain.LoginUserFieldInfo;
import com.ht.common.core.enums.AuthStatusEnum;
import com.ht.common.core.enums.UserStatus;
import com.ht.common.core.enums.UserTypeEnum;
import com.ht.common.core.exception.ServiceException;
import com.ht.common.core.text.Convert;
import com.ht.common.core.utils.DateUtils;
import com.ht.common.core.utils.StringUtils;
import com.ht.common.core.utils.ip.IpUtils;
import com.ht.common.core.web.domain.AjaxResult;
import com.ht.common.redis.service.RedisService;
import com.ht.common.security.utils.SecurityUtils;
import com.ht.system.domain.BaseFieldInfo;
import com.ht.system.domain.EnterpriseInfo;
import com.ht.system.domain.SysRole;
import com.ht.system.domain.SysUser;
import com.ht.system.service.*;
import com.ht.system.util.RsaUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 登录校验方法
 *
 * @author ruoyi
 */
@Component
public class SysLoginService
{
    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private SysRecordLogService recordLogService;

    @Autowired
    private RedisService redisService;
    @Autowired
    private ISysPermissionService sysPermissionService;

    @Autowired
    private ISysRoleService sysRoleService;
    @Autowired
    private IEnterpriseInfoService enterpriseInfoService;
    @Autowired
    private IBaseFieldInfoService baseFieldInfoService;

    /**
     * 登录
     */
    public LoginUser login(String username, String orgpassword)
    {
        String password= null;
        try {
            password = RsaUtils.decryptByPrivateKey(orgpassword);
        } catch (Exception e) {
            throw new ServiceException("密码错误");
        }
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
            throw new ServiceException("用户/密码必须填写");
        }

        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
            throw new ServiceException("用户密码不在指定范围");
        }
        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
            throw new ServiceException("用户名不在指定范围");
        }
        // IP黑名单校验
        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾，访问IP已被列入系统黑名单");
            throw new ServiceException("很遗憾，访问IP已被列入系统黑名单");
        }
        // 查询用户信息
        SysUser user = sysUserService.selectUserByUserName(username);

        if (null==user)
        {
            throw new ServiceException("用户不存在");
        }
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new ServiceException("对不起，您的账号：" + username + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + username + " 已停用");
        }
        if(!AuthStatusEnum.AUTH_PASS.getCode().equals(user.getAuthStatus()) && !SecurityUtils.isAdmin(user.getUserId())){
            throw new ServiceException("对不起，您的账号：" + username + " 未认证");
        }
        passwordService.validate(user, password);
        LoginUser userInfo =new LoginUser();
        userInfo.setIpaddr(IpUtils.getIpAddr());


        List<SysRole> roleList=  sysRoleService.selectRolesByUserId(user.getUserId());
        if(StringUtils.isNotEmpty(roleList)){
            Set<String> roleSet=roleList.stream().map(n->n.getRoleKey()).collect(Collectors.toSet());
            userInfo.setRoles(roleSet);
        }
        Set<String> perSet=  sysPermissionService.getMenuPermission(user);
        userInfo.setPermissions(perSet);
        userInfo.setLoginTime(new Date().getTime());
       //userInfo.setCheckType(user.getCheckType());
        userInfo.setUsername(user.getUserName());
        userInfo.setAvatar(user.getAvatar());
        userInfo.setNickname(user.getNickName());
        userInfo.setUserId(user.getUserId());
        userInfo.setUserType(user.getUserType());
        //加载用户企业
        if(UserTypeEnum.isEntUser(user.getUserType())&&StringUtils.isNotBlank(user.getEntCode())){
           setUserEntInfo(user,userInfo);
        }
        //加载用户场所信息
        if(UserTypeEnum.isFieldUser(user.getUserType())&&StringUtils.isNotBlank(user.getFieldCode())){
           setUserFieldInfo(user,userInfo);
        }
        if(userInfo.isAdmin()){
            setUserEntInfo(user,userInfo);
            setUserFieldInfo(user,userInfo);
        }

        recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
        recordLoginInfo(user.getUserId());
        return userInfo;
    }

    /**
     * 微信登录
     */
    public AjaxResult wxLogin(String username, String password)
    {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
           return AjaxResult.error("用户/密码必须填写");
        }

        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
            return AjaxResult.error("用户密码不在指定范围");
        }
        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
            return AjaxResult.error("用户名不在指定范围");
        }
        // IP黑名单校验
        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "很遗憾，访问IP已被列入系统黑名单");
            return AjaxResult.error("很遗憾，访问IP已被列入系统黑名单");
        }
        // 查询用户信息
        SysUser user = sysUserService.selectUserByUserName(username);

        if (null==user)
        {
            return AjaxResult.error("用户不存在");
        }
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "对不起，您的账号已被删除");
            return AjaxResult.error("对不起，您的账号：" + username + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用，请联系管理员");
            return AjaxResult.error("对不起，您的账号：" + username + " 已停用");
        }
        if(!AuthStatusEnum.AUTH_PASS.getCode().equals(user.getAuthStatus()) && !SecurityUtils.isAdmin(user.getUserId())){
            return AjaxResult.error("对不起，您的账号：" + username + " 未认证");
        }
        passwordService.validate(user, password);
        LoginUser userInfo =new LoginUser();
        userInfo.setIpaddr(IpUtils.getIpAddr());


        List<SysRole> roleList=  sysRoleService.selectRolesByUserId(user.getUserId());
        if(StringUtils.isNotEmpty(roleList)){
            Set<String> roleSet=roleList.stream().map(n->n.getRoleKey()).collect(Collectors.toSet());
            userInfo.setRoles(roleSet);
        }
        Set<String> perSet=  sysPermissionService.getMenuPermission(user);
        userInfo.setPermissions(perSet);
        userInfo.setLoginTime(new Date().getTime());
        //userInfo.setCheckType(user.getCheckType());
        userInfo.setUsername(user.getUserName());
        userInfo.setAvatar(user.getAvatar());
        userInfo.setNickname(user.getNickName());
        userInfo.setUserId(user.getUserId());
        userInfo.setUserType(user.getUserType());
        //加载用户企业
        if(UserTypeEnum.isEntUser(user.getUserType())&&StringUtils.isNotBlank(user.getEntCode())){
            setUserEntInfo(user,userInfo);
        }
        //加载用户场所信息
        if(UserTypeEnum.isFieldUser(user.getUserType())&&StringUtils.isNotBlank(user.getFieldCode())){
            setUserFieldInfo(user,userInfo);
        }
        if(userInfo.isAdmin()){
            setUserEntInfo(user,userInfo);
            setUserFieldInfo(user,userInfo);
        }

        recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
        recordLoginInfo(user.getUserId());
        return AjaxResult.success(userInfo);
    }

    /**
     * 加载用户场所
     * @param user
     */
    private void setUserFieldInfo( SysUser user,LoginUser userInfo) {
        BaseFieldInfo bif=  baseFieldInfoService.selectBaseFieldInfoByFieldCode(user.getFieldCode());
        if(null==bif){
            throw new ServiceException("当前用户关联的场所不存在");
        }
        LoginUserFieldInfo loginUserFieldInfo=new LoginUserFieldInfo();
        loginUserFieldInfo.setCustomsCode(bif.getCustomsCode());
        loginUserFieldInfo.setCustomsName(bif.getCustomsCode());
        loginUserFieldInfo.setFieldCode(bif.getFieldCode());
        loginUserFieldInfo.setFieldName(bif.getFieldName());
        userInfo.setLoginUserFieldInfo(loginUserFieldInfo);
    }

    /**
     * 加载用户企业信息
     * @param userInfo
     */
    private void setUserEntInfo( SysUser user,LoginUser userInfo) {
        //加载企业信息
        EnterpriseInfo ep=  enterpriseInfoService.selectByEntCode(user.getEntCode());
        if(null==ep){
            throw new ServiceException("当前用户关联的企业备案不存在");
        }
        LoginUserEntInfo lue=new LoginUserEntInfo();
        lue.setEntCode(ep.getEntCode());
        lue.setEntName(ep.getEntName());
        lue.setEntType(ep.getEntType());
        userInfo.setLoginUserEntInfo(lue);
    }

    /**
     * 记录登录信息
     *
     * @param userId 用户ID
     */
    public void recordLoginInfo(Long userId)
    {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        // 更新用户登录IP
        sysUser.setLoginIp(IpUtils.getIpAddr());
        // 更新用户登录时间
        sysUser.setLoginDate(DateUtils.getNowDate());
        sysUserService.updateUserHeadInfo(sysUser);
    }

    public void logout(String loginName)
    {
        recordLogService.recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
    }


    public AjaxResult getLoinUser() {
        AjaxResult ajax = AjaxResult.success();
        LoginUser user = SecurityUtils.getLoginUser();
        if(null==user){
            throw  new ServiceException("用户未登录");
        }
        SysUser su= sysUserService.selectUserById(user.getUserId());
        if(null==su){
            throw  new ServiceException("用户未登录");
        }
        //边民刷身份证登录后前端调用getInfo时，如果是边民则初始化边民互市、互市场所作业平台给用户访问。正常账号登录的逻辑未变动。
        // 角色集合
        Set<String> roles = sysPermissionService.getRolePermission(su);
        // 权限集合
        Set<String> permissions = sysPermissionService.getMenuPermission(su);
        //允许访问的平台
        if (user.isAdmin()) {
           // List<String> platformList = sysPlatformMapper.getPlatform();
            //user.setPlatforms(platformList.toArray(new String[platformList.size()]));
        } else {
           // String platform = sysUserMapper.getPlatform(user.getUserId());
            //user.setPlatforms(StringUtils.isNotEmpty(platform) ? platform.split(",") : null);
        }
        su.setPassword("");
        ajax.put("user", su);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }
}
